package com.swak.fx.support.ui;

import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.ObservableValue;
import javafx.geometry.VPos;
import javafx.scene.Node;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Priority;

/**
 * 表单项
 * 
 * @author 618lf
 */
public class UIFormItem extends GridPane implements UILifecycle {

	// ================================================================================
	// Properties
	// ================================================================================
	private final String STYLE_CLASS = "ui-form-item";
	private final String CONTENT_STYLE_CLASS = "ui-form-content";
	private final String LABEL_STYLE_CLASS = "ui-form-label";
	private final String TIP_STYLE_CLASS = "ui-form-tip";
	private final String STYLESHEET = UI.load("css/UIFormItem.css");

	Node labelNode;
	Node contentNode;
	Node tipNode;

	public UIFormItem() {
		super();
		init();
	}

	@Override
	public void initializeParts() {
		getStyleClass().add(STYLE_CLASS);
	}

	@Override
	public void layoutParts() {
		int column = 0;
		int row = 0;
		if (labelNode != null) {
			this.add(labelNode, column, 0);
			GridPane.setValignment(labelNode, VPos.TOP);
			column++;
			row++;
		}
		if (contentNode != null) {
			this.add(contentNode, column, 0);
			GridPane.setFillWidth(contentNode, true);
			GridPane.setHgrow(contentNode, Priority.ALWAYS);
			row++;
		}
		if (tipNode != null) {
			this.add(tipNode, column, row >= 1 ? 1 : 0);
			GridPane.setFillWidth(tipNode, true);
			GridPane.setHgrow(tipNode, Priority.ALWAYS);
		}
	}

	@Override
	public void setupValueChangedListeners() {
		contentProperty.addListener(this::onItemChange);
		labelProperty.addListener(this::onLabelChange);
		tipProperty.addListener(this::onTipChange);
	}

	private void onItemChange(ObservableValue<? extends Node> observable, Node oldValue, Node newValue) {
		this.getChildren().removeAll(labelNode, contentNode, tipNode);
		this.contentNode = newValue;
		if (this.contentNode != null) {
			this.contentNode.getStyleClass().add(CONTENT_STYLE_CLASS);
		}
		this.layoutParts();
		this.requestLayout();
	}

	private void onLabelChange(ObservableValue<? extends Node> observable, Node oldValue, Node newValue) {
		this.getChildren().removeAll(labelNode, contentNode, tipNode);
		this.labelNode = newValue;
		if (this.labelNode != null) {
			this.labelNode.getStyleClass().add(LABEL_STYLE_CLASS);
		}
		this.layoutParts();
		this.requestLayout();
	}

	private void onTipChange(ObservableValue<? extends Node> observable, Node oldValue, Node newValue) {
		this.getChildren().removeAll(labelNode, contentNode, tipNode);
		this.tipNode = newValue;
		if (this.tipNode != null) {
			this.tipNode.getStyleClass().add(TIP_STYLE_CLASS);
		}
		this.layoutParts();
		this.requestLayout();
	}

	// ================================================================================
	// Property
	// ================================================================================
	private ObjectProperty<Node> contentProperty = new SimpleObjectProperty<>(this, "formContent");
	private ObjectProperty<Node> labelProperty = new SimpleObjectProperty<>(this, "formLabel");
	private ObjectProperty<Node> tipProperty = new SimpleObjectProperty<>(this, "formTip");

	public ObjectProperty<Node> contentProperty() {
		return contentProperty;
	}

	public UIFormItem Content(Node node) {
		contentProperty.set(node);
		return this;
	}

	public ObjectProperty<Node> labelProperty() {
		return labelProperty;
	}

	public UIFormItem Label(Node node) {
		labelProperty.set(node);
		return this;
	}

	public ObjectProperty<Node> tipProperty() {
		return tipProperty;
	}

	public UIFormItem Tip(Node node) {
		tipProperty.set(node);
		return this;
	}

	// ================================================================================
	// Overridden Methods
	// ================================================================================

	@Override
	public String getUserAgentStylesheet() {
		return STYLESHEET;
	}
}